﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using _180FrameWork.DataBaseHelper.Entities;

namespace _180FrameWork.DataBaseHelper.OracleExtend
{
    public class OracleSqlBuilder : ISqlBuilder
    {
        private string _paramChar = ":";

        private IDictionary<RuntimeTypeHandle, DataBaseTableSchedule> _catchList;

        private IDictionary<RuntimeTypeHandle, DataBaseTableSchedule> catchList
        {
            get
            {
                if (this._catchList == null)
                {
                    this._catchList = new Dictionary<RuntimeTypeHandle, DataBaseTableSchedule>();
                }
                return this._catchList;
            }
        }

        object locker = new object();

        #region ORM扩展
        /// <summary>
        /// 获取结构
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private DataBaseTableSchedule getDataBaseTableSchedule<T>()
        {
            lock (locker)
            {
                var type = typeof(T);
                DataBaseTableSchedule schedule = null;
                if (this.catchList.ContainsKey(type.TypeHandle))
                {
                    schedule = this.catchList[type.TypeHandle];
                }
                else
                {
                    schedule = new DataBaseTableSchedule(type);
                    this.catchList.Add(type.TypeHandle, schedule);
                }
                return schedule;
            }
        }
        /// <summary>
        /// 获取查找SQL语句
        /// </summary>
        /// <param name="Schedule"></param>
        /// <param name="tran"></param>
        /// <returns></returns>
        public string GetSelectSQL<T>()
        {
            var schedule = getDataBaseTableSchedule<T>();
            StringBuilder strSQL = new StringBuilder();
            strSQL.AppendFormat("select ");
            foreach (var column in schedule.ColumnNoPrimaryKeyList)
            {
                if (column.ColumnName == column.PropertieName)
                {
                    strSQL.AppendFormat("{0},", column.ColumnName);
                }
                else
                {
                    strSQL.AppendFormat("{0} as \"{1}\",", column.ColumnName, column.PropertieName);
                }
            }
            strSQL.Remove(strSQL.Length - 1, 1);
            strSQL.AppendFormat(" from {0} where 1=1", schedule.TableName);
            //根据表名获取主键
            foreach (var key in schedule.PrimaryKeyList)
            {
                strSQL.AppendFormat(" and {0}=" + _paramChar + "{1}", key.ColumnName, key.PropertieName);
            }
            return strSQL.ToString();
        }
        /// <summary>
        /// 获取插入SQL语句
        /// </summary>
        /// <param name="Schedule"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public string GetInsertSQL<T>()
        {
            var schedule = getDataBaseTableSchedule<T>();
            StringBuilder strSQL = new StringBuilder();
            strSQL.AppendFormat("insert into {0}(", schedule.TableName);
            foreach (var item in schedule.ColumnList)
            {
                strSQL.Append(item.ColumnName + ",");
            }
            strSQL.Remove(strSQL.Length - 1, 1);
            strSQL.Append(")values(");
            foreach (var item in schedule.ColumnList)
            {
                strSQL.Append(this._paramChar + item.PropertieName + ",");
            }
            strSQL.Remove(strSQL.Length - 1, 1);
            strSQL.Append(")");
            return strSQL.ToString();
        }

        /// <summary>
        /// 获取更新SQL语句
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="data"></param>
        /// <param name="tran"></param>
        /// <returns></returns>
        public string GetUpdateSQL<T>(object data)
        {
            var pi = data.GetType().GetProperties();

            StringBuilder strSQL = new StringBuilder();

            var schedule = getDataBaseTableSchedule<T>();
            if (schedule.PrimaryKeyList.Count > 0)
            {
                strSQL.AppendFormat("update {0} set ", schedule.TableName);

                foreach (var p in pi)
                {
                    object val = p.GetValue(data, null);
                    if (val != null)
                    {
                        foreach (var item in schedule.ColumnNoPrimaryKeyList)
                        {
                            if (item.PropertieName == p.Name)
                            {
                                strSQL.Append(item.ColumnName + "=" + this._paramChar + item.PropertieName + ",");
                            }
                        }
                    }
                }

                strSQL.Remove(strSQL.Length - 1, 1);
                strSQL.Append(" where 1=1 ");
                foreach (var item in schedule.PrimaryKeyList)
                {
                    strSQL.Append(" and " + item.ColumnName + "=" + this._paramChar + item.PropertieName + "");
                }
                return strSQL.ToString();
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 获取删除SQL语句
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="data"></param>
        /// <param name="tran"></param>
        /// <returns></returns>
        public string GetDeleteSQL<T>()
        {
            StringBuilder strSQL = new StringBuilder();
            var schedule = getDataBaseTableSchedule<T>();
            if (schedule.PrimaryKeyList.Count > 0)
            {
                strSQL.AppendFormat("delete from {0} where 1=1 ", schedule.TableName);
                foreach (var item in schedule.PrimaryKeyList)
                {
                    strSQL.Append(" and " + item.ColumnName + "=" + this._paramChar + item.ColumnName + "");
                }
                return strSQL.ToString();
            }
            else
            {
                return null;
            }
        }      
        #endregion
    }
}
